#include "main.h"

int32_t main(int argc,char* argv[])
{
	pid_t pid;
	pid=fork();
	escribir_logfile("DiscoSO", 0, INFOs, "Fork() OK");
	if (pid==0){
		sleep(2);
		execv("/home/utn_so/Escritorio/Workspace/Disco/Consola/Consola",argv);
	}
	else
	{
	Encolados=0;
	cargarConfiguracion(ArrayConf,ArrayConfAlgoritmo);
	escribir_logfile("DiscoSO", 0, INFOs, "Archivo de Configuracion OK");
	IniciarDisco(archDisco);
	escribir_logfile("DiscoSO", 0, INFOs, "Disco Inicializado");
	pthread_mutex_init (&mutexBuffer, NULL);
	pthread_mutex_init (&mutexCabezal, NULL);
	pthread_mutex_init (&mutexEncolar, NULL);
	IniciarAtenderConsola();
	escribir_logfile("DiscoSO", 0, INFOs, "Consola Conectada");
	if(strcmp(ArrayConf[0],"LISTEN")==0)
	{
		sockGral = IniciarSocketListen();
		printf("Esperando Conexion de PFS \n");
		//sockRAID = accept(sockGral,NULL,NULL);
		//Handshake();
	}
	else
	{
		int portAux = atoi(ArrayConf[11]);
		conectar(ArrayConf[10],portAux);
	}
	if(strcmp(ArrayConf[1],"SSTF")==0)
	{
		escribir_logfile("DiscoSO", 0, INFOs, "Algoritmo con inanicion SSTF");
		IniciarSSTF();

	}
	else
	{
		escribir_logfile("DiscoSO", 0, INFOs, "Algoritmo sin inanicion CSCAN");
		IniciarCSCAN();
	}
	///EscribirSector(2,"INICIO--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------FIN000");
	///LeerSector(2);
	printf("\n");
	pthread_join( HiloCola, NULL);
	pthread_join(HiloConsola,NULL);
	return 0;
	}
}

void IniciarAtenderConsola()
{
	char* message;
	int32_t  iCola;
	iCola=pthread_create( &HiloConsola, NULL, AtenderConsola,(void*) message);
}

void Handshake()
{
	char* recvBuff = malloc(16+1+2+1+4);
	int32_t rc=recv(sockRAID,recvBuff,16+1+2+1+4,0);
	if(rc > 0)
	{
		escribir_logfile("DiscoSO", 0, INFOs, "HandShake PFS");
	}
	free(recvBuff);
	    char*  bufferSalida;
	    Paquete* unPaquete = malloc (sizeof(Paquete));
	    RandomGG(unPaquete->ID,16);
	    unPaquete->Tipo = HANDSHAKE_OK;
	    unPaquete->Length = 0;
	    unPaquete->Datos = malloc (1);
	    unPaquete->Datos = '\0';
	    bufferSalida = Serializar(unPaquete);
	    if ( send(sockRAID, bufferSalida, 16+1+4+2+1, 0) < 0)
	    {
	    	escribir_logfile("DiscoSO", 0, ERROR, "Error HandShake PFS");
	    }
	    free( bufferSalida );
	    free(unPaquete->Datos);
	    free(unPaquete);
}

void* AtenderConsola(void)
{
		/*Variables Locales*/
		int32_t sockConsole=-1;
		newSockConsole=-1;
		int32_t rc=-1;
		char* bufferEntrada=(char*)malloc(BUFFER_MAX);
		Paquete* data=(Paquete*)malloc(sizeof(Paquete));

		/*Establecer Conexiones*/
		sockConsole = initSockConsole();
	    if ( sockConsole < 0 )
	    	exit(127);
	    newSockConsole = accept(sockConsole, NULL, NULL);
		if (newSockConsole < 0)
			exit(127);
		rc = read(newSockConsole, bufferEntrada, BUFFER_MAX);
		data=DesSerializar(bufferEntrada);
		if ( data->Tipo == HANDSHAKE_CONSOLE)
		{
			data->Tipo = HANDSHAKE_OK;
			char* serial;
			data->Length=1;
			serial = Serializar(data);
			rc = send(newSockConsole,serial,512+16+1+2+4,0);
			free(serial);
		    if (rc < 0)
				exit(127);

		}
		else
			exit(1);
		while(1)
		{
						int params[5];
			  			rc = read(newSockConsole, bufferEntrada, BUFFER_MAX);
			  			data->Datos=malloc(512);
			  			data=DesSerializar(bufferEntrada);
			  			if (rc < 1){
			  				exit(127);
			  			}
			  			if (data->Tipo == INFO)
			  			{
			  				pthread_mutex_lock (&mutexCabezal);
			  				int32_t unaPistita=Cabezal / atoi(ArrayConfAlgoritmo[5]);
			  				int32_t unSectorcito=Cabezal - unaPistita*(atoi(ArrayConfAlgoritmo[5]));
			  				pthread_mutex_unlock (&mutexCabezal);
			  				char* letsSend = malloc(1*200);
			  				sprintf(letsSend,"Pista:%d , Sector:%d \n",unaPistita,unSectorcito);
			  				send(newSockConsole,letsSend,512+16+1+2+4,0);
			  				//free(letsSend);
			  			}
			  			if (data->Tipo == TRACE)
			  			{
			  				int32_t j = 0;
			  				if(data->Datos[0]!='(')
			  					send(newSockConsole,"Error Comando TRACE \n",512+16+1+2+4,0);
			  				else
			  				{
			  					for(int32_t i=0; i<data->Length;i++)
			  					{
			  						if(data->Datos[i]==',')
			  							j++;
			  					}
			  					int32_t pos = 1;
			  					int32_t x = 0;
			  					char* num1=malloc(10);
			  					char* num2=malloc(10);
			  					char* num3=malloc(10);
			  					char* num4=malloc(10);
			  					char* num5=malloc(10);
			  					int32_t var1 = -1;
			  					int32_t var2 = -1;
			  					int32_t var3 = -1;
			  					int32_t var4 = -1;
			  					int32_t var5 = -1;
			  					/*if(j==0)
			  					{
				  					while(data->Datos[pos]!=')')
				  					{
				  						num1[x]=data->Datos[pos];
				  						x++;
				  						pos++;
				  					}
				  					var1=atoi(num1);
			  					}
			  					else
			  					{*/
			  						if(j>0)
			  						{
					  					while(data->Datos[pos]!=',')
					  					{
					  						num2[x]=data->Datos[pos];
					  						x++;
					  						pos++;
					  					}
					  					var2=atoi(num2);
					  					pos++;
					  					x=0;
			  						}
			  						if(j>1)
			  						{
					  					while(data->Datos[pos]!=',')
					  					{
					  						num3[x]=data->Datos[pos];
					  						x++;
					  						pos++;
					  					}
					  					var3=atoi(num3);
					  					pos++;
					  					x=0;
			  						}
			  						if(j>2)
			  						{
					  					while(data->Datos[pos]!=',')
					  					{
					  						num4[x]=data->Datos[pos];
					  						x++;
					  						pos++;
					  					}
					  					var4=atoi(num4);
					  					pos++;
					  					x=0;
			  						}
			  						if(j>3)
			  						{
					  					while(data->Datos[pos]!=',')
					  					{
					  						num5[x]=data->Datos[pos];
					  						x++;
					  						pos++;
					  					}
					  					var5=atoi(num5);
					  					pos++;
					  					x=0;
			  						}
				  					while(data->Datos[pos]!=')')
				  					{
				  						num1[x]=data->Datos[pos];
				  						x++;
				  						pos++;
				  					}
				  					var1=atoi(num1);
				  					Trace(var1,var2,var3,var4,var5);
			  					}
			  				}


			  			if (data->Tipo == CLEAN)
			  			{
			  				int32_t fd = fileno_unlocked(archDisco);
			  				posix_fadvise(fd,0,0,2);
			  				if(data->Datos[0]!='(')
			  					send(newSockConsole,"Error Comando CLEAN \n",512+16+1+2+4,0);
			  				else
			  				{
			  					int32_t pos = 1;
			  					int32_t x = 0;
			  					char* num1=malloc(10);
			  					char* num2=malloc(10);
			  					int32_t var1,var2;
			  					while(data->Datos[pos]!=',')
			  					{
			  						num1[x]=data->Datos[pos];
			  						x++;
			  						pos++;
			  					}
			  					num1[x]='\0';
			  					var1=atoi(num1);
			  					pos++;
			  					x=0;
			  					while(data->Datos[pos]!=')')
			  					{
			  						num2[x]=data->Datos[pos];
			  						x++;
			  						pos++;
			  					}
			  					num2[x]='\0';
			  					var2=atoi(num2);
			  					if(var1>var2)
			  						send(newSockConsole,"Error Comando CLEAN \n",512+16+1+2+4,0);
			  					else
			  					{
			  					Clean(var1,var2);
			  					send(newSockConsole,"CLEAN OK \n",512+16+1+2+4,0);
			  					}
			  				}
			  				fd = fileno_unlocked(archDisco);
			  				posix_fadvise(fd,0,0,1);
			  			}
		}
			  			free(data->Datos);
		            }

void Trace(int32_t var1,int32_t var2,int32_t var3,int32_t var4,int32_t var5)
{
	for(int32_t i = 0; i<16;i++)
		IDTrace[i]='W';
	Solicitud unaSolicitud;
	for(int32_t i = 0; i<16;i++)
		unaSolicitud.ID[i]='W';
	unaSolicitud.Sector=var1;
	unaSolicitud.Tipo='L';
	pthread_mutex_lock(&mutexEncolar);
	if(unaSolicitud.Sector!=-1)
		EncolarPedido(unaSolicitud);
	Solicitud unaSolicitud2;
	for(int32_t i = 0; i<16;i++)
		unaSolicitud2.ID[i]='W';
	unaSolicitud2.Sector=var2;
	unaSolicitud2.Tipo='L';
	if(unaSolicitud2.Sector!=-1)
		EncolarPedido(unaSolicitud2);
	Solicitud unaSolicitud3;
	for(int32_t i = 0; i<16;i++)
		unaSolicitud3.ID[i]='W';
	unaSolicitud3.Sector=var3;
	unaSolicitud3.Tipo='L';
	if(unaSolicitud3.Sector!=-1)
		EncolarPedido(unaSolicitud3);
	Solicitud unaSolicitud4;
	for(int32_t i = 0; i<16;i++)
		unaSolicitud4.ID[i]='W';
	unaSolicitud4.Sector=var4;
	unaSolicitud4.Tipo='L';
	if(unaSolicitud4.Sector!=-1)
		EncolarPedido(unaSolicitud4);
	Solicitud unaSolicitud5;
	for(int32_t i = 0; i<16;i++)
		unaSolicitud5.ID[i]='W';
	unaSolicitud5.Sector=var5;
	unaSolicitud5.Tipo='L';
	if(unaSolicitud5.Sector!=-1)
		EncolarPedido(unaSolicitud5);
	pthread_mutex_unlock(&mutexEncolar);
}

void Clean(int32_t var1,int32_t var2)
{
	while(var1<=var2)
	{
		char* fill = malloc(512);
		fill="00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
		Solicitud unaSolicitud;
		for(int32_t i=0;i<512;i++)
			unaSolicitud.Datos[i]=fill[i];
		RandomGG(unaSolicitud.ID,16);
		unaSolicitud.Sector=var1;
		unaSolicitud.Tipo='E';
		pthread_mutex_lock(&mutexEncolar);
		EncolarPedido(unaSolicitud);
		pthread_mutex_unlock(&mutexEncolar);
		var1++;
	}
}




